using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

using Acms.SqlDal;

namespace Acms.Bll
{
    public class Post : BaseItem
    {
        protected Post() : base() { }

        protected Post(Hashtable table) : base(table) { }

        protected Post(Hashtable table, ICollection collection) : base(table, collection) { }

        public static Post CreateInstance()
        {
            return new Post();
        }

        protected override Base CreateDal()
        {
            return new PostDal();
        }

        private static Post Get(Hashtable table)
        {
            if (table == null)
            {
                return null;
            }
            else
            {
                return new Post(table);
            }

        }

        private static List<Post> Get(Hashtable[] tables)
        {
            if (tables == null)
            {
                return null;
            }
            else
            {
                List<Post> tmp = new List<Post>();
                foreach (Hashtable table in tables)
                {
                    tmp.Add(new Post(table, tmp));
                }
                return tmp;
            }
        }

        public static Post GetTopLevelBySiteId(int siteId)
        {
            PostDal dal = new PostDal();
            return Get(dal.GetTopLevelBySiteId(siteId));

        }

        public static Post GetTopLevelBySiteIdAndMenuId(int siteId, int menuId)
        {
            PostDal dal = new PostDal();
            return Get(dal.GetTopLevelBySiteIdAndMenuId(siteId, menuId));

        }

        public static List<Post> GetAllBySiteIdMenuIdAndParentPath(int siteId, int menuId, string parentPath)
        {
            PostDal dal = new PostDal();
            return Get(dal.GetAllBySiteIdMenuIdAndParentPath(siteId, menuId, parentPath));
        }

        public static List<Post> GetAllBySiteIdAndParentPath(int siteId, string parentPath)
        {
            PostDal dal = new PostDal();
            return Get(dal.GetAllBySiteIdParentPath(siteId, parentPath)); 
        }

        public static List<Post> GetAllByMenuIdAndParentId(int menuId, int parentId)
        {
            PostDal dal = new PostDal();
            return Get(dal.GetAllByMenuIdAndParentId(menuId, parentId));
        }
        
        public static List<Post> GetAllByParentId(int parentId)
        {
            PostDal dal = new PostDal();
            return Get(dal.GetAllByParentId(parentId));
        }

        public static Post GetBySiteUrlAndPostUrl(string siteUrl, string postUrl)
        {
            PostDal dal = new PostDal();
            return Get(dal.GetBySiteUrlAndPostUrl(siteUrl, postUrl));
        }

        public static Post GetBySiteIdAndUrl(int siteId, string url)
        {
            PostDal dal = new PostDal();
            return Get(dal.GetBySiteIdAndUrl(siteId, url));
        }

        public static Post GetBySiteIdMenuIdAndUrl(int siteId, int menuId, string url)
        {
            PostDal dal = new PostDal();
            return Get(dal.GetBySiteIdMenuIdAndUrl(siteId, menuId, url));
        }

        public static List<Post> GetAllByParentIdAndTopicId(int parentId, int topicId, bool includeChildren, int startIndex, int pageSize, ref int totalRecords)
        {
            PostDal dal = new PostDal();
            return Get(dal.GetAllByParentIdAndTopicId(parentId, topicId, includeChildren, startIndex, pageSize, ref totalRecords));
        }

        public static Post GetById(int id)
        {
            PostDal dal = new PostDal();
            return Get(dal.GetById(id));
        }

        protected override void Load(Hashtable table)
        {
            id = (int)table[PostDal.Fields.Id];
            siteId = (int)table[PostDal.Fields.SiteId];
            siteName = (string)table[PostDal.Fields.SiteName];
            parentId = (int?)table[PostDal.Fields.ParentId];
            parentPath = (string)table[PostDal.Fields.ParentPath]; 
            name = (string)table[PostDal.Fields.Name];
            displayName = (string)table[PostDal.Fields.DisplayName];
            templateId = (int)table[PostDal.Fields.TemplateId];
            templateName = (string)table[PostDal.Fields.TemplateName];
            thumbnailId = (int?)table[PostDal.Fields.ThumbnailId];
            summary = (string)table[PostDal.Fields.Summary];
            tags = (string)table[PostDal.Fields.Tags];
            sequence = (int)table[PostDal.Fields.Sequence];
            createdDateTime = (DateTime)table[PostDal.Fields.CreatedDateTime];
        }

        private int id;
        public int Id
        {
            get { return id; }
        }

        private int siteId;
        public int SiteId
        {
            get { return siteId; }
            set { siteId = value; }
        }

        private string siteName;
        public string SiteName
        {
            get { return siteName; }
        }
        
        private int? parentId;
        public int? ParentId
        {
            get { return parentId; }
            set { parentId = value; }
        }

        private Post parent;
        public Post Parent
        {
            get 
            {
                if (parent == null && parentId.HasValue && parentId.Value > 0)
                {
                    parent = Post.GetById(parentId.Value);
                }
                return parent;
            }
        }

        private string name;
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        private string displayName;
        public string DisplayName
        {
            get { return displayName; }
            set { displayName = value; }
        }

        private string parentPath;
        public string ParentPath
        {
            get { return parentPath; }
        }

        public string Path
        {
            get { return string.Concat(ParentPath, Name); }
        }
        public string Url
        {
            get 
            {
                if (this.Id > 0 && this.Path != "~")
                {
                    return string.Format("{0}{1}.aspx", ParentPath, this.Name);
                }
                else if (this.Id > 0 && this.Path == "~")
                {
                    return "~/default.aspx";
                }
                else
                {
                    return null;
                }
            }
        }

        public string ParentUrl
        {
            get
            {
                if (parentId > 0 && ParentPath != null)
                {
                    //remove final / from parent path
                    return string.Format("{0}.aspx", ParentPath.Substring(0, ParentPath.Length - 1));
                }
                else
                {
                    return null;
                }
            }
        }


        private int? thumbnailId;
        public int? ThumbnailId
        {
            get { return thumbnailId; }
            set { thumbnailId = value; }
        }

        private int templateId;
        public int TemplateId
        {
            get { return templateId; }
            set 
            { 
                if(templateId != value)
                {
                    templateId = value; 
                    template = null;
                }
            }
        }

        private Template template;
        public Template Template 
        {
            get
            {
                if (template == null && TemplateId > 0)
                {
                    template = Bll.Template.GetById(TemplateId);
                }
                return template;
            }
        }

        private string templateName;
        public string TemplateName
        {
            get { return templateName; }
        }

        private string summary;
        public string Summary
        {
            get { return summary; }
            set { summary = value;}
        }

        private string tags;
        public string[] Tags
        {
            get
            {
                if (tags != null)
                {
                    return tags.Substring(1, tags.Length - 2).Split('|');
                }
                else
                {
                    return new string[0];
                }
            }
        }

        public void AddTag(string tag)
        {
            if(!string.IsNullOrEmpty(tag))
            {
                if (tags == null)
                {
                    tags = "|";
                }
                tags = string.Concat(tags, tag, "|");
            }
        }

        public void RemoveTag(string tag)
        {
            if (tags != null)
            {
                tags = tags.Replace(string.Concat("|", tag, "|"), "|");
            }
        }

        public bool HasTag(string tag)
        {
            if(string.IsNullOrEmpty(tag) || tags == null)
            {
                return false;
            }
            else
            {
                return tags.Contains(string.Concat("|", tag, "|"));
            }
        }

        private int sequence;
        public int Sequence
        {
            get { return sequence; }
            set { sequence = value; }
        }

        private DateTime createdDateTime;
        public DateTime CreatedDateTime
        {
            get { return createdDateTime; }
        }

        public new void Update()
        {
            base.Update();
        }

        protected override void SaveChanges(ref object concurencyId, Base dal)
        {
            bool commitTran = false;
            if (IsNewRecord && base.TransactionKey != Guid.Empty )
            {
                commitTran = true;
                base.UseTransaction(dal.StartTransaction());
            }
            ((PostDal)dal).Update(ref id, siteId, ref siteName, parentId, ref parentPath, name, displayName, templateId, ref templateName, thumbnailId, summary, tags, ref sequence, ref createdDateTime, ref concurencyId);
            if (IsNewRecord)
            {
                List<Menu> menus = Menu.GetAllBySiteId(SiteId);
                foreach (Acms.Bll.Menu m in menus)
                {
                    Acms.Bll.PostMenu pm = Acms.Bll.PostMenu.CreateInstance(id, m.Id, m.DefaultForAllPosts);
                    pm.UseTransaction(base.TransactionKey);
                    pm.Update();
                }
            }
            if (commitTran)
            {
                base.CommitTransaction();
            }
        }

        public new void Delete()
        {
            base.Delete();
        }

        protected override void DeleteRecord(object concurencyId, Base dal)
        {
            ((PostDal)dal).Delete(id, concurencyId);
        }

        private List<PostControl> controls;
        public List<PostControl> Controls
        {
            get
            {
                if (controls == null && this.Id > 0)
                {
                    controls = Bll.PostControl.GetAllByPostId(Id);
                }
                return controls;
            }
        }

        public PostControl FindPostControl(string name)
        {
            if (Controls != null)
            {
                foreach (PostControl ctrl in Controls)
                {
                    if (ctrl.Name == name)
                    {
                        return ctrl;
                    }
                }
            }
            return null;
        }

        private List<Post> children;
        public List<Post> Children
        {
            get 
            {
                if (children == null)
                {
                    children = Post.GetAllByParentId(this.Id);
                }
                return children;
            }
        }

        public Post FindChildByName(string name)
        {
            if (string.IsNullOrEmpty(name))
                return null;
            foreach (Post p in Children)
            {
                if (p.Name.ToLower() == name.ToLower())
                    return p;
            }
            return null;
        }


        private List<Topic> topics;
        public List<Topic> GetTopics()
        {
            if (topics == null)
            {
                topics = Topic.GetAllByPostId(this.Id);
            }
            return topics;
        }

        public Topic GetFirstTopic()
        {
            List<Topic> tmp = GetTopics();
            if (tmp != null && tmp.Count > 0)
            {
                return tmp[0];
            }
            else
            {
                return null;
            }
        }

        private TemplateFile defaultFile;
        public TemplateFile GetDefaultFile()
        {
            if (defaultFile == null)
            {
                defaultFile = TemplateFile.GetDefault(this.TemplateId);
            }
            return defaultFile;
        }

        private Dictionary<string, TemplateFile> files;
        public TemplateFile GetFile(string name)
        {
            if (files == null)
            {
                files = new Dictionary<string, TemplateFile>();
            }
            if (!files.ContainsKey(name))
            {
                files.Add(name, TemplateFile.GetByTemplateIdAndName(this.TemplateId, name));
            }
            return files[name];
        }

        public string GetDefaultQueryString()
        {
            return GetQueryString(GetDefaultFile());
        }

        public string GetQueryString(string name)
        {
            return GetQueryString(GetFile(name));
        }

        public string GetQueryString(TemplateFile file)
        {
            if (file != null)
            {
                System.Text.StringBuilder queryString = new StringBuilder();
                queryString.AppendFormat("AcmsPostId={0}", Id);
                queryString.AppendFormat("&AcmsSiteId={0}", SiteId);
                if (!string.IsNullOrEmpty(file.MasterPagePath))
                    queryString.AppendFormat("&AcmsMasterPagePath={0}", file.MasterPagePath);
                if (!string.IsNullOrEmpty(file.Path))
                    queryString.AppendFormat("&AcmsTemplatePath={0}", file.Path);
                if (!string.IsNullOrEmpty(file.Theme))
                    queryString.AppendFormat("&AcmsTheme={0}", file.Theme);
                return queryString.ToString();
            }
            else
            {
                return null;
            }
        }
    }
}
